#pragma once

#include <memory>
#include <chrono>
#include <string_view>

#include "thread_task.h"

namespace thread {

class ThreadPool;
/**
 * 线程池线程
 */
class TPThread {
  friend class ThreadPool;

  class Impl;

 public:
  enum class State : uint8_t;

  /**
   * @param thread_pool   创建线程的线程池
   * @param wait_second   空闲等待时间 小于0为永久线程
   */
  TPThread(std::weak_ptr<ThreadPool> &&thread_pool,
           std::chrono::seconds wait_second = std::chrono::seconds(-1));
  virtual ~TPThread();

  /**
   * 线程创建
   */
  void Create(std::string prefix = "TPThread");

  /**
   * 线程函数 启动后调用的函数
   */
  void ThreadFunc();

  /**
   * 线程启动时操作
   */
  virtual void OnStart();

  /**
   * 线程结束时操作
   */
  virtual void OnEnd();

  /**
   * 任务处理开始时操作
   */
  virtual void OnProcessTaskStart(ThreadTask *task);

  /**
   * 任务处理
   */
  virtual void ProcessTask(ThreadTask *task);

  /**
   * 任务处理结束时操作
   */
  virtual void OnProcessTaskEnd(ThreadTask *task);

  /**
   * 获取hash后的唯一线程id
   */
  size_t GetThreadId() const;

  /**
   * 获取线程名称
   */
  std::string_view GetThreadName() const;

  /**
   * 获取线程状态
   */
  TPThread::State GetState() const;

  /**
   * 等待线程结束
   */
  void Join();

  /**
   * 线程分离
   */
  void Detach();

  /**
   * 从线程池中获取下一个任务
   */
  virtual ThreadTask *GetNextTask();

  /**
   * 获取当前的任务
   */
  ThreadTask *GetCurrentTask() const;

  /**
   * 设置当前线程任务
   */
  void SetCurrentTask(ThreadTask *task);

  /**
   * 获取线程池
   */
  ThreadPool *GetThreadPool() const;

  /**
   * 重置任务计数
   * @note 线程启动一次在未改变到闲置状态下连续执行的任务计数
   */
  void ResetTaskCounter();

  /**
   * 增加任务计数
   */
  void IncTaskCounter();

  /**
   * 输出线程工作状态 watcher用
   */
  virtual std::string PrintState();

 public:
  /**
   * 线程状态
   */
  enum class State : uint8_t {
    kStateStop    = -1,  // 未启动
    kStateSleep   = 0,   // 睡眠
    kStateBusy    = 1,   // 繁忙
    kStateEnd     = 2,   // 结束
    kStatePending = 3,   // 等待
  };

 private:
  std::unique_ptr<Impl> impl_;
};

}  // namespace thread